/*
* Purpose: Audio task for sending data to DAC.
*
* Author: Allen Lin
*
* Date: 2008/5/22
*
* Copyright Generalplus Corp. ALL RIGHTS RESERVED.
*
* Version : 1.00
* History :
*/
#include "application.h"

typedef struct
{
	INT32S	curr_play_time;
	INT32S	total_play_time;
} ST_AUDIO_PLAY_TIME;

#define AUDIO_DAC_QUEUE_MAX		10
#define AUDIO_DAC_SENDQ_SIZE	MAX_DAC_BUFFERS

// Variables defined in this file
/* Task Q declare */
OS_EVENT *hAudioDacTaskQ;
OS_EVENT *aud_send_q;
void *AudioDacTaskQ_area[AUDIO_DAC_QUEUE_MAX];
void *send_q[AUDIO_DAC_SENDQ_SIZE];
INT32U last_send_idx;

ST_AUDIO_PLAY_TIME	aud_time;

void audio_dac_task_init(void)
{
	/* Create MsgQueue/MsgBox for TASK */
	hAudioDacTaskQ = OSQCreate(AudioDacTaskQ_area, AUDIO_DAC_QUEUE_MAX);
	aud_send_q = OSQCreate(send_q, AUDIO_DAC_SENDQ_SIZE);
}

void audio_dac_task_entry(void *para)
{
	INT8U	err = 0;
	INT32S	audio_dac_msg;
	INT8U	pause = 0;
	INT32U	r_idx = 0;
	INT32U	w_idx = 0;
	INT8U	reverse = 0;
	INT32U	total_samples = 0;
	INT32U	pcmlen;

	double	times;

#if AUDIO_PRIOR_DYNAMIC_SW == 1
	INT32U	hiprio_en = 0;
	INT8U	audio_playing = 0;
	OS_Q	*pq;
#endif
	audio_dac_task_init();

	DBG_PRINT("%s ... \r\n", __func__);

	/* Task Star */
	while(1)
	{
		/* Pend task message */
		audio_dac_msg = (INT32S) OSQPend(hAudioDacTaskQ, 0, &err);

		switch(audio_dac_msg)
		{
		case C_DMA_STATUS_DONE:
			if(pause != 1)
			{
#if AUDIO_PRIOR_DYNAMIC_SW == 1
				pq = (OS_Q *) aud_send_q->OSEventPtr;
				if((pq->OSQEntries < 3) && !hiprio_en && audio_playing)
				{
					OSTaskChangePrio(PRIORITY_AUD_DEC, PRIORITY_AUD_DEC_HIGH);
					hiprio_en = 1;

					//DBG_PRINT("hi prio\r\n");
				}
				else
				if(hiprio_en && (pq->OSQEntries > 4))
				{
					OSTaskChangePrio(PRIORITY_AUD_DEC_HIGH, PRIORITY_AUD_DEC);
					hiprio_en = 0;

					//DBG_PRINT("low prio\r\n");
				}

#endif
				r_idx = (INT32U) OSQAccept(aud_send_q, &err);
				if(err == OS_NO_ERR)
				{
					dac_cha_dbf_set(pcm_out[r_idx], pcm_len[r_idx]);
					last_send_idx = r_idx;
				}
				else
				{
					dac_audop_speaker_en(0);   // mute
				}
			}

			if(music_para.audio_format == AUDIO_TYPE_WAV)
			{
				pcmlen = pcm_len[w_idx];
				if(channel == 2)
				{
					pcmlen >>= 1;
				}

				if(reverse == 0)
				{
					total_samples += pcmlen;
				}
				else
				{
					if(total_samples >= pcmlen)
					{
						total_samples -= pcmlen;
					}
					else
					{
						total_samples = 0;
					}
				}

				times = (double) total_samples / (double) g_audio_sample_rate;

				if(((INT32U) times > aud_time.curr_play_time) || ((INT32U) times < aud_time.curr_play_time))
				{
					aud_time.curr_play_time = (INT32U) times;

					//					if (start_time_send && aud_time.curr_play_time <=  aud_time.total_play_time) {
					//						msgQSend(ApQ, MSG_AUD_PLAY_TIME_RES, (void *)&aud_time, sizeof(STAudioConfirm), MSG_PRI_NORMAL);
					//					}
				}
			}

			OSQPost(audio_wq, (void *) w_idx);
			if(++w_idx == dac_buf_nums)
			{
				w_idx = 0;
			}

			break;

#if AUDIO_PRIOR_DYNAMIC_SW == 1

		case MSG_AUD_LOW_PRIORITY_SET:
			if(hiprio_en)
			{
				OSTaskChangePrio(PRIORITY_AUD_DEC_HIGH, PRIORITY_AUD_DEC);
				hiprio_en = 0;

				//DBG_PRINT("recovery to low prio\r\n");
			}

			break;

		case MSG_AUD_DAC_STOP:
			audio_playing = 0;
			break;
#endif

		case MSG_AUD_DMA_DBF_START:
			r_idx = (INT32U) OSQAccept(aud_send_q, &err);
			dac_cha_dbf_put(pcm_out[r_idx], pcm_len[r_idx], hAudioDacTaskQ);
			r_idx = (INT32U) OSQAccept(aud_send_q, &err);
			dac_cha_dbf_set(pcm_out[r_idx], pcm_len[r_idx]);
			pause = 0;
			dac_audop_speaker_en(1);

#if AUDIO_PRIOR_DYNAMIC_SW == 1
			audio_playing = 1;
#endif

			//DBG_PRINT("dma start\r\n");
			break;

		case MSG_AUD_DMA_DBF_RESTART:
			r_idx = (INT32U) OSQAccept(aud_send_q, &err);
			if(err == OS_NO_ERR)
			{
				dac_cha_dbf_set(pcm_out[r_idx], pcm_len[r_idx]);
				dac_audop_speaker_en(1);
			}

			DBG_PRINT("D..\r\n");
			break;

		case MSG_AUD_DMA_WIDX_CLEAR:
			w_idx = 0;
			break;

		case MSG_AUD_DMA_PAUSE:
			pause = 1;

			//DBG_PRINT("dma pause\r\n");
			break;

		case MSG_AUD_START_SAMPLES_COUNT:
			total_samples = 0;
			aud_time.total_play_time = total_play_time;
			aud_time.curr_play_time = 0;
			if(start_time_send)
			{
				msgQSend(ApQ, MSG_AUD_PLAY_TIME_RES, (void *) &aud_time, sizeof(STAudioConfirm), MSG_PRI_NORMAL);
			}

			break;

		case MSG_AUD_DAC_REVRESE:
			reverse = 1;
			break;

		case MSG_AUD_DAC_REVRESE_CLEAR:
			reverse = 0;
			break;

		default:
			break;
		}
	}
}
